home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / util / passwd / passwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-03  |  6.3 KB  |  270 lines

  1. RCS_ID_C="$Id: passwd.c,v 1.5 1994/05/02 19:52:55 jraja Exp $";
  2. /*
  3.  * passwd.c -- change password
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * Copyright © 1994 AmiTCP/IP Group, <AmiTCP-group@hut.fi>
  8.  *                  Helsinki University of Technology, Finland.
  9.  *
  10.  * Created      : Tue Jan 11 14:06:41 1994 ppessi
  11.  * Last modified: Sun Feb 27 03:45:36 1994 ppessi
  12.  *
  13.  */
  14.  
  15. #include "passwd_rev.h"
  16.  
  17. static const char version[] = VERSTAG " "
  18.   "Copyright © 1994 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  19.   "Helsinki University of Technology, Finland.\n";
  20.  
  21. /****** utilities/passwd *****************************************************
  22.  
  23.     NAME
  24.         passwd - modify a user's password
  25.  
  26.     VERSION
  27.         $Id: passwd.c,v 1.5 1994/05/02 19:52:55 jraja Exp $
  28.  
  29.     SYNOPSIS
  30.         passwd [user]
  31.  
  32.     FUNCTION
  33.  
  34.         Passwd changes the user's password.  First, the user is prompted for
  35.         their current password.  If the current password is correctly typed, a
  36.         new password is requested.  The new password must be entered twice to
  37.         avoid typing errors.
  38.  
  39.         The new password should be at least six characters long and not purely
  40.         alphabetic.  Its total length must be less than _PASSWORD_LEN
  41.         (currently 128 characters).  Numbers, upper case letters and meta
  42.         characters are en­ couraged.
  43.  
  44.         Once the password has been verified, passwd communicates the new
  45.         password information to the netinfo.device.
  46.  
  47.         The super-user is not required to provide a user's current password.
  48.  
  49.     FILES
  50.  
  51.     SEE ALSO
  52.         login
  53.  
  54.         Robert Morris, and Ken Thompson, UNIX password security.
  55.  
  56.     HISTORY
  57.         A passwd command appeared in Version 6 AT&T UNIX.
  58.  
  59. ****************************************************************************
  60. */
  61.  
  62. #if defined(__SASC)
  63. extern struct ExecBase *SysBase;
  64. #include <pragmas/exec_sysbase_pragmas.h>
  65. #include <clib/exec_protos.h>
  66. #include <proto/usergroup.h>
  67. #include <proto/dos.h>
  68. /* Disable ^C signaling */
  69. void __regargs __chkabort(void) {}
  70. #else
  71. #include <clib/exec_protos.h>
  72. #include <clib/usergroup_protos.h>
  73. #include <clib/dos_protos.h>
  74. #endif
  75.  
  76. #include <dos/rdargs.h>
  77.  
  78. #include <sys/time.h>
  79. #include <sys/param.h>
  80.  
  81. #include <string.h>
  82. #include <stdlib.h>
  83. #include <ctype.h>
  84.  
  85. #include <pwd.h>
  86. #include <grp.h>
  87. #include <unistd.h>
  88. #include <errno.h>
  89.  
  90. #include "config.h"
  91.  
  92. #include <bsdsocket.h>
  93.  
  94. BPTR Stdin, Stdout, Stderr;
  95. APTR WinPtr = NULL;
  96. struct RDArgs *rdargs = NULL;
  97. struct MsgPort *port = NULL;
  98. struct NetInfoReq *req = NULL;
  99. short device_is_open = 0;
  100.  
  101. static void resume_amiga_stdio(void)
  102. {
  103.   struct Process* me = (struct Process *)FindTask(NULL);
  104.   me->pr_WindowPtr = WinPtr;
  105.  
  106.   if (rdargs)
  107.     FreeArgs(rdargs);
  108.   rdargs = NULL;
  109.  
  110.   if (device_is_open) 
  111.     CloseDevice((struct IORequest *)req);
  112.   if (req)
  113.     DeleteIORequest((struct IORequest *)req);
  114.   if (port)
  115.     DeleteMsgPort(port);
  116. }
  117.  
  118. static void startup_amiga_stdio(void)
  119. {
  120.   struct Process* me = (struct Process *)FindTask(NULL);
  121.   Stdin = me -> pr_CIS;
  122.   Stdout = me -> pr_COS;
  123.   Stderr = (me -> pr_CES ? me -> pr_CES : Stdout);
  124.  
  125.   /* Remove requesters */
  126.   WinPtr = me->pr_WindowPtr;
  127.   me->pr_WindowPtr = (void *)-1L;
  128.   atexit(resume_amiga_stdio);
  129. }
  130.  
  131. int local_passwd(char *uname);
  132. char *getnewpasswd(struct passwd *pw);
  133. void pw_update(struct passwd *pw);
  134.  
  135. void main(void)
  136. {
  137.   const char *template = 
  138.     "USERNAME";
  139.   struct {
  140.     STRPTR a_name;
  141.   } args[1] = { 0 };
  142.  
  143.   startup_amiga_stdio();
  144.  
  145.   rdargs = ReadArgs((STRPTR)template, (LONG *)args, NULL);
  146.   if (!rdargs) {
  147.     PrintFault(IoErr(), "passwd");
  148.     exit(RETURN_ERROR);
  149.   } 
  150.  
  151.   if (args->a_name) {
  152.     exit(local_passwd(args->a_name));
  153.   } else {
  154.     char *uname = getlogin();
  155.     if (uname)
  156.       exit(local_passwd(uname));
  157.     
  158.     FPrintf(Stderr, "passwd: no user");
  159.     exit(RETURN_ERROR);
  160.   }
  161. }
  162.  
  163. static uid_t uid;
  164.  
  165. int local_passwd(char *uname)
  166. {
  167.   struct passwd *pw;
  168.  
  169.   if (!(pw = getpwnam(uname))) {
  170.     (void)FPrintf(Stderr, "passwd: unknown user %s.\n", uname);
  171.     exit(RETURN_ERROR);
  172.   }
  173.  
  174.   uid = getuid();
  175.   if (uid && uid != pw->pw_uid) {
  176.     (void)FPrintf(Stderr, "passwd: %s\n", ug_StrError(EACCES));
  177.     exit(RETURN_ERROR);
  178.   }
  179.  
  180.   /*
  181.    * Get the new password.
  182.    */
  183.   pw->pw_passwd = getnewpasswd(pw);
  184.   
  185.   pw_update(pw);
  186.   return 0;
  187. }
  188.  
  189. char *getnewpasswd(struct passwd *pw)
  190. {
  191.   register char *p, *t;
  192.   int tries;
  193.   char buf[_PASSWORD_LEN+1], salt[16];
  194.  
  195.   (void)Printf("Changing password for %s.\n", pw->pw_name);
  196.  
  197.   if (uid && pw->pw_passwd && pw->pw_passwd[0] &&
  198.       strcmp(crypt(getpass("Old password:"), pw->pw_passwd),
  199.          pw->pw_passwd)) {
  200.     (void)FPrintf(Stderr, "passwd: %s\n", ug_StrError(EACCES));
  201.     exit(RETURN_ERROR);
  202.   }
  203.  
  204.   for (buf[0] = '\0', tries = 0;;) {
  205.     p = getpass("New password:");
  206.     if (!*p) {
  207.       (void)PutStr("Password unchanged.\n");
  208.       exit(RETURN_ERROR);
  209.     }
  210.     if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
  211.       (void)PutStr("Please enter a longer password.\n");
  212.       continue;
  213.     }
  214.     for (t = p; *t && islower(*t); ++t);
  215.     if (!*t && (uid != 0 || ++tries < 2)) {
  216.       (void)PutStr("Please don't use an all-lower case password.\n"
  217.            "Unusual capitalization, control characters or "
  218.            "digits are suggested.\n");
  219.       continue;
  220.     }
  221.     (void)strncpy(buf, p, _PASSWORD_LEN);
  222.     if (!strcmp(buf, getpass("Retype new password:")))
  223.       break;
  224.     (void)Printf("Mismatch; try again, EOF to quit.\n");
  225.   }
  226.  
  227.   strncpy(salt, pw->pw_passwd, sizeof(salt));
  228.   salt[8] = '\0';
  229.   ug_GetSalt(pw, salt, sizeof(salt));
  230.  
  231.   return(crypt(buf, salt));
  232. }
  233.  
  234. #include <devices/netinfo.h>
  235.  
  236. void pw_update(struct passwd *pw)
  237. {
  238.   if (port = CreateMsgPort()) 
  239.     req = CreateIORequest(port, sizeof(*req));
  240.   if (!port || !req) {
  241.     PrintFault(ERROR_NO_FREE_STORE, "CreateIORequest");
  242.     exit(RETURN_FAIL);
  243.   }
  244.  
  245.   if (OpenDevice(NETINFONAME, NETINFO_PASSWD_UNIT, 
  246.          (struct IORequest *)req, 0L)) {
  247.     Printf("%s: %s\n", NETINFONAME, ug_StrError(req->io_Error));
  248.     exit(RETURN_FAIL);
  249.   }
  250.  
  251.   device_is_open = 1;
  252.  
  253.   req->io_Data = pw;
  254.   req->io_Command = CMD_WRITE;
  255.   DoIO(req);
  256.   if (req->io_Error) {
  257.     Printf("%s (%s): %s\n", NETINFONAME, "CMD_WRITE", 
  258.        ug_StrError(req->io_Error));
  259.     exit(RETURN_FAIL);
  260.   }
  261.  
  262.   req->io_Command = CMD_UPDATE;
  263.   DoIO(req);
  264.   if (req->io_Error) {
  265.     Printf("%s (%s): %s\n", NETINFONAME, "CMD_UPDATE", 
  266.        ug_StrError(req->io_Error));
  267.     exit(RETURN_FAIL);
  268.   }
  269. }
  270.